;^Z80^ ; modem control information ; Coleco 300 baud direct connect modem ; 4/5/84 ; ; Data port = 05EH ; Control port = 05FH ; ; Useful equates DATAP EQU 05EH CTRLP EQU 05FH ; ; Mode instruction values NULL EQU 080H ; ; To generate mode byte, select one from column A ; and one from column B. See your INTEL dealer for optional ; accessories. Add these all together, and spit 'em out. ; Chef's suggestion: DEFAULT EQU STPB1+BITS7+PEN+EP ; [7 bits, 1 stop bit, even parity] ; ; column A STPB1 EQU 040H ; 1 stop bit STPB15 EQU 080H ; 1 1/2 stop bits STPB2 EQU 0C0H ; 2 stop bits ; column B BITS5 EQU 000H ; 5 bits/char BITS6 EQU 004H ; 6 bits/char BITS7 EQU 008H ; 7 bits/char BITS8 EQU 00CH ; 8 bits/char ; optional accessories EP EQU 020H ; 1=even parity, 0=odd PEN EQU 010H ; 1=enable parity, 0=disable ; required options ; ---> The only one applicable here is 300 baud!!! <--- X64 EQU 003H ; 64x clock rate [300 baud] ; ; the assumed default value DEFAULT EQU STPB2+BITS8 ; 8 bits, 2 stops, no parity ; Command instruction values ; ; Select desired functions, then add to get command byte ; EHM EQU 080H ; 1=enter hunt mode [no effect on async op] ; [same as NULL] IR EQU 040H ; 1=internal reset RTS EQU 020H ; 1=set RTS to 0, enable transmitter ER EQU 010H ; 1=reset error conditions SBRK EQU 008H ; 1=send break [TXD goes "low"] RXE EQU 004H ; 1=receive enable TXE EQU 001H ; 1=transmit enable DTR EQU 002H ; set DTR to 0, seize phone line ; ; Note this important stuff | ; V ; 1: If DTR ever gets set to 0, [SZ or preset goes low] then ; modem goes to originate mode. ; 2: Once line is seized, DTR is set to 1, ^SZ is low, so ; 7474 has preset=H, data=L,.html clear=H. In this condition, ; toggling clock [RTS or ^TXE] will change to answer mode ; ; So what? ; ; With phone hung up, modem is in originate mode. To seize line, ; set DTR and RTS to 1 [this drops ^SZ]. This grabs phone line ; and enables carrier. ; To switch to answer mode, set RTS to 0 then back to 1. ; ; STATUS BITS ; TXRDY EQU 0 ; indicates transmitter empty RXRDY EQU 1 ; indicates valid character ready TXMT EQU 2 ; indicates buffer empty P_ERR EQU 3 ; set when parity error detected OE EQU 4 ; set on overrun error FE EQU 5 ; set on framing error BD EQU 6 ; set when break detected DSR EQU 7 ; indicated carrier detect CD EQU DSR ; ; data areas C_DATA DEFB NULL ; current 8251 command ; ; global subroutine names ; GLOBAL DELAY,DIAL,SEIZE,ANSMOD GLOBAL HANGUP,CD_STAT,U_STAT GLOBAL CHR_IN,CHR_OUT,M_INIT GLOBAL SET_UART ; ;*************************************************************************** ; SUBROUTINES ;*************************************************************************** ; ; Wait 10 msec DELAY: PUSH AF ; [3 uSEC] PUSH BC ; [3] PUSH DE ; [3] PUSH HL ; [3] LD HL,0 ; [2.5] LD DE,0 ; [2.5] LD BC,1590 ; with all the pushes and pops, we've used about 32 uSEC. ; we need a total of 2,000 LDIRs less 7 ; BUT this is off a bit, so we have to go about 18% faster LDIR POP HL ; [3] POP DE ; [3] POP BC ; [3] POP AF ; [3] RET ; ; ************************************* ; DIAL DIGIT ; ENTRY: A=ASCII DIGIT 0-9 ; EXIT: NONE DIAL: PUSH AF PUSH BC PUSH DE PUSH HL ;thaT CP 'P' JR Z,PAUSE CP 'p' JR Z,PAUSE CP ',' ;Comma=pause JR Z,PAUSE CP '9'+1 JR NC,BAD_DGT ;if character >= ':' then we lose CP '0' JR C,BAD_DGT ;if char < '0' then we lose JR NZ,CHAR_OK ; an ASCII 0 means 10 pulses, so start with '9'+1 LD A,'9'+1 CHAR_OK: SUB '0' LD B,A ;number of pulses is now in B ; PLSE_LP: ; All dialing is in originate mode. We assume that the line was ; already seized. ; ; unseize line for 18/29 of the 100 ms pulse time [60 ms] LD A,RXE+TXE+RTS OUT (CTRLP),A ;PICK UP PUSH BC LD B,6 PLP1: CALL DELAY DJNZ PLP1 POP BC ; seize line for 11/29 of the 100 ms pulse time [40 ms] LD A,RXE+TXE+RTS+DTR OUT (CTRLP),A ;PICK UP PUSH BC LD B,4 PLP2: CALL DELAY DJNZ PLP2 POP BC ; ; next pulse DJNZ PLSE_LP LD (C_DATA),A ;SAVE LAST VALUE ; ; delay between digits PAUSE: LD B,80 ;800 ms PLP3: CALL DELAY DJNZ PLP3 BAD_DGT: POP HL POP DE POP BC POP AF RET ; *************************** ; SEIZE LINE ; ENTRY: A=0 FOR ORIGINATE MODE ; A-0FFH FOR ANSWER MODE ; EXIT: CARRIER IS ENABLED ; REGS A & C GET TRASHED SEIZE: LD C,A ; SAVE CALL HANGUP LD A,RXE+TXE+RTS+DTR LD (C_DATA),A ; SAVE LAST COMMAND OUT (CTRLP),A ; PICK UP LD A,C OR A RET Z ; ALL DONE ; ***************** ; ANSWER MODE ; SWITCHES MODEM DIRECTLY TO ANSWER MODE ; Assumes modem off-hook ; EXIT: REG A TRASHED ANSMOD: ; ONE FULL PULSE OF RTS LINE LD A,RXE+TXE+DTR OUT (CTRLP),A LD A,RXE+TXE+RTS+DTR LD (C_DATA),A ; SAVE LAST COMMAND OUT (CTRLP),A RET ; ********************** ; HANGUP ; HANGS UP PHONE. TRASHES REG A ; HANGUP: LD A,RXE+TXE+RTS LD (C_DATA),A ; SAVE LAST COMMAND OUT (CTRLP),A ; HANG UP PHONE AND SWITCH TO ORIGINATE MODE RET ; ********************** ; CARRIER_STATUS ; READS STATUS FROM UART AND MODEM CHIP ; ENTRY: ; EXIT: NZ=CARRIER DETECT ; Z=NO CARRIER CD_STAT: IN A,(CTRLP) BIT DSR,A RET ; ********************** ; UART_STATUS ; CHECKS UART FOR ERRORS AND/OR DATA ; ENTRY: ; EXIT: NC=NO ERRORS ; C=DATA ERROR ; NZ=CHARACTER PRESENT ; Z=NO CHARACTER U_STAT: IN A,(CTRLP) OR A JR URT_CMN URT_ERR: SCF URT_CMN: BIT RXRDY,A RET ; ************************ ; CHARACTER_IN ; ENTRY: ; EXIT: A=CHARACTER FROM MODEM ; NC=NO ERROR ; C=DATA ERROR CHR_IN: CALL U_STAT JR Z,CHR_IN ;WAIT FOR CHARACTER IN A,(DATAP) OR A RET CHR_ERR: LD A,(C_DATA) OR ER ;clear for errors OUT (CTRLP),A XOR ER ;disable error reset OUT (CTRLP),A LD A,0 RET ; ********************* ; CHARACTER_OUT ; ENTRY: A=CHARACTER TO TRANSMIT ; EXIT: NONE CHR_OUT: PUSH AF ; WAIT UNTIL TRANSMITTER CLEAR CHR_L1: IN A,(CTRLP) BIT TXMT,A JR Z,CHR_L1 ; DUMP THE SUCKER OUT POP AF OUT (DATAP),A RET ; ************************* ; MODEM_INIT ; PRESETS MODEM TO KNOWN INITIAL STATE M_INIT: LD A,NULL LD (C_DATA),A ; fool it into hanging up LD A,DEFAULT ; desired default value ; ************************* ; SET_UART ; SETS UART TO DESIRED STOP BITS, PARITY, ETC ; ENTRY: A=stop bits + bits/char + parity ; EXIT: NONE SET_UART: OR X64 ; clock rate is always 64x PUSH AF LD A,080H OUT (CTRLP),A OUT (CTRLP),A ; get the 8251's attention LD A,040H OUT (CTRLP),A POP AF OUT (CTRLP),A ; dump the init value out LD A,(C_DATA) OUT (CTRLP),A RET